package base.loader
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	
	import utils.StringUtil;
	
	[Event(name="complete",type="flash.events.Event")]
	public class BaseLoader extends EventDispatcher
	{
		protected var _id:int;
		protected var _urlLoader:URLLoader;
		protected var _urlRequest:URLRequest;
		protected var _urlVariables:URLVariables;
		protected var _requestMethod:String;
		protected var _url:String;
		protected var _isComplete:Boolean;
		protected var _isSuccess:Boolean;
		protected var _isLoading:Boolean;
		protected var _progress:Number;
		protected var _repeat:int;
		protected var _currentRepeat:int=1;
		public function get currentRepeat():int
		{
			return _currentRepeat;
		}

		protected var _transferData:*;
		/**
		 *加载优先级 
		 */		
		protected var _level:int;

		/**
		 *加载失败提示语 
		 */		
		public var loadErrorMessage:String;
		/**
		 *加载分类类别，用来区别当前加载所属 
		 */		
		protected var _loaderFlagType:String;
		protected var _loaderVersion:int=0;
		public var isDispose:Boolean=false;
		
		public function BaseLoader(loaderFlagType:String, id:int, url:String, repeat:int=3, urlVariables:URLVariables=null, requestMethod:String=URLRequestMethod.GET, loaderVersion:int=0, level:int=0)
		{
			_loaderFlagType=loaderFlagType;
			_id=id;
			_url=url;
			_repeat=repeat;
			_urlVariables=urlVariables;
			_requestMethod=requestMethod;
			_loaderVersion=loaderVersion;
			_urlLoader=new URLLoader();
			_urlRequest=new URLRequest();
			_level=level;
			addEvent();
		}

		/**
		 *增加事件 
		 */		
		protected function addEvent():void
		{
			_urlLoader.addEventListener(Event.COMPLETE, __onCompleted);
			_urlLoader.addEventListener(ProgressEvent.PROGRESS, __onProgress);
			_urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, __onHttpStatus);
			_urlLoader.addEventListener(IOErrorEvent.IO_ERROR, __onError);
			_urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, __onError);
		}
		
		/**
		 *移除事件 
		 */		
		protected function removeEvent():void
		{
			if(_urlLoader)
			{
				_urlLoader.removeEventListener(Event.COMPLETE, __onCompleted);
				_urlLoader.removeEventListener(ProgressEvent.PROGRESS, __onProgress);
				_urlLoader.removeEventListener(HTTPStatusEvent.HTTP_STATUS, __onHttpStatus);
				_urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, __onError);
				_urlLoader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, __onError);
			}
		}
		
		/**
		 * 执行加载(如果直接执行加载,其加载将不会载入加载列表,也将会忽略自身在缓存中的已加载项)
		 */
		public function execute():void
		{
			LoaderFactory.Instance.executeLoader(this);
		}
		
		/**
		 * 执行加载(如果直接执行加载,其加载将不会载入加载列表,也将会忽略自身在缓存中的已加载项)
		 */
		public function executeGo():void
		{
			if(_isComplete)
			{//如果已经加载成功过，直接发出完成事件
				loaderComplete();
				return;
			}
			if(_isLoading) return;//如果在加载进行中，则返回
			
			_urlLoader.dataFormat = getDataFormat();
			if(StringUtil.contains(_url, "?"))
			{
				if(_loaderVersion>0)
				{
					_urlRequest.url=_url+"&v="+_loaderVersion;
				}
				else
				{
					_urlRequest.url=_url+"&v="+Math.random();
				}
			}
			else
			{
				if(_loaderVersion>0)
				{
					_urlRequest.url=_url+"?v="+_loaderVersion;
				}
				else
				{
					_urlRequest.url=_url+"?v="+Math.random();
				}
			}
			if(_currentRepeat>1)
			{
				_urlRequest.url+="&r="+Math.random();
			}
			_urlRequest.data=_urlVariables;
			_urlRequest.method=_requestMethod;
			_isLoading=true;
//			_isComplete=false;
//			_isSuccess=false;
			trace(_urlRequest.url);
			_urlLoader.load(_urlRequest);
		}
		
		/**
		 *加载成功事件
		 */
		protected function __onCompleted(evt:Event):void
		{
			removeEvent();
			_progress=100;
			_isComplete=true;
			_isLoading=false;
			_isSuccess=true;
			loaderComplete();
		}
		
		protected function loaderComplete():void
		{
			dispatchEvent(new LoaderEvent(LoaderEvent.PROGRESS,this));
			dispatchEvent(new LoaderEvent(LoaderEvent.COMPLETE,this));
		}
		
		/**
		 *加载错误事件
		 */
		protected function __onError(evt:Event):void
		{
			_isComplete=true;
			_isLoading=false;
			_isSuccess=false;
			loadError();
		}
		
		/**
		 *加载进度事件
		 */		
		protected function __onProgress(evt:ProgressEvent):void
		{
			_progress = evt.bytesLoaded/evt.bytesTotal*100;
			dispatchEvent(new LoaderEvent(LoaderEvent.PROGRESS,this));
		}
		
		/**
		 *当前Http状态事件
		 */		
		protected function __onHttpStatus(evt:HTTPStatusEvent):void
		{
			if(evt.status > 399)
			{
				loadError();
			}
			dispatchEvent(new LoaderEvent(LoaderEvent.HTTP_STATUS,this));
		}
		
		/**
		 *加载错误处理 
		 */		
		protected function loadError():void
		{
			if(_currentRepeat < _repeat)
			{
				_currentRepeat++;
				_isLoading = false;
				_isComplete=false;
				_isSuccess=false;
				executeGo();//执行立即加载
			}
			else
			{
				
				_isLoading = false;
				_isSuccess = false;
				if(_currentRepeat<=_repeat)
				{
					_currentRepeat++;
					_isComplete = false;
					LoaderFactory.Instance.executeLoader(this);//放到加载列表后面再加载一次
				}
				else
				{
					_isComplete = true;
					dispatchEvent(new LoaderEvent(LoaderEvent.LOAD_ERROR,this));
					loaderComplete();
				}
			}
		}
		
		protected function getDataFormat():String
		{
			return URLLoaderDataFormat.BINARY;
		}
		
		/**
		 *是否正在加载中 
		 */		
		public function get isLoading():Boolean
		{
			return _isLoading;
		}
		
		/**
		 *是否加载成功 
		 */		
		public function get isSuccess():Boolean
		{
			return _isSuccess;
		}
		
		/**
		 *是否已执行完加载(并不代表加载成功) 
		 */		
		public function get isComplete():Boolean
		{
			return _isComplete;
		}
		
		/**
		 *要加载的URL 
		 */		
		public function get url():String
		{
			return _url;
		}
		
		/**
		 *加载项分配的ID 
		 */		
		public function get id():int
		{
			return _id;
		}
		
		/**
		 *加载后的数据 
		 */		
		public function get data():*
		{
			return _urlLoader.data;
		}
		
		/**
		 *加载进度百分比 
		 */		
		public function get progress():Number
		{
			return _progress;
		}
		
		/**
		 *取得失败后,重复加载次数 
		 */		
		public function get repeat():int
		{
			return _repeat;
		}

		/**
		 *需要传递的数据(方便使用,不会对该数据做任何处理)
		 */		
		public function get transferData():*
		{
			return _transferData;
		}

		/**
		 *需要传递的数据(方便使用,不会对该数据做任何处理)
		 */
		public function set transferData(value:*):void
		{
			_transferData = value;
		}
		
		public function clone():BaseLoader
		{
			var baseLoader:BaseLoader=new BaseLoader(_loaderFlagType, _id, _url, _repeat, _urlVariables, _requestMethod, _loaderVersion);
			baseLoader.isComplete=_isComplete;
			baseLoader.isSuccess=_isSuccess;
			baseLoader.isLoading=_isLoading;
			baseLoader.progress=_progress;
			return baseLoader;
		}
		
		public function dispose():void
		{
			isDispose=true;
			LoaderFactory.Instance.delExecuteLoader(this);
			removeEvent();
			_transferData=null;
			if(_urlRequest)
			{
				_urlRequest.requestHeaders=null;
				_urlRequest.data=null;
			}
			_urlRequest=null;
			_urlVariables=null;
			if(_urlLoader)
			{
				if(_isLoading)_urlLoader.close();
//				if(_urlLoader.data && _urlLoader.data is ByteArray)(_urlLoader.data as ByteArray).clear();
				_urlLoader.data=null;
			}
			_urlLoader=null;
		}

		/**
		 *加载分类类别，用来区别当前加载所属 
		 */
		public function get loaderFlagType():String
		{
			return _loaderFlagType;
		}

		public function set isComplete(value:Boolean):void
		{
			_isComplete = value;
		}

		public function set isSuccess(value:Boolean):void
		{
			_isSuccess = value;
		}

		public function set isLoading(value:Boolean):void
		{
			_isLoading = value;
		}

		/**
		 *加载进度,100为加载完成值 
		 */
		public function set progress(value:Number):void
		{
			_progress = value;
		}

		/**
		 *加载优先级 
		 */
		public function get level():int
		{
			return _level;
		}
	}
}